<!DOCTYPE html>
<html>

<head>
    <script src="https://unpkg.com/konva@8.3.5/konva.min.js"></script>
    <script src="./js/quilli.js"></script>
    <link rel="stylesheet" href="./css/quilli.snow.css" />

    <script src="https://html2canvas.hertzen.com/dist/html2canvas.min.js"></script>
    <meta charset="utf-8" />
    <title>Konva Rich text on Canvas Demo</title>
    <style>
        body {
            margin: 0;
            padding: 0;
            overflow: hidden;
            background-color: #f0f0f0;
        }

        #editor-container {}

        .ql-editor {
            overflow: visible;
        }
    </style>
</head>

<body>
    <div id="editor-container">
        That is <u>some</u> <span style="color: red"> styled text</span> on
        <strong>canvas</strong>!
        <h2>What do you think about it?</h2>
    </div>
    Rendered stage:
    <div id="container"></div>
    <script>
        var quill = new Quill('#editor-container', {
            modules: {
                toolbar: [
                    [{ header: [1, 2, false] }],
                    ['bold', 'italic', 'underline'],
                    ['image', 'code-block'],
                ],
            },
            placeholder: 'Compose an epic...',
            theme: 'snow', // or 'bubble'
        });

        var width = window.innerWidth;
        var height = window.innerHeight;

        var stage = new Konva.Stage({
            container: 'container',
            width: width,
            height: height,
        });

        const layer = new Konva.Layer();
        stage.add(layer);

        const shape = new Konva.Image({
            x: 20,
            y: 20,
            draggable: true,
            stroke: 'red',
            scaleX: 1 / window.devicePixelRatio,
            scaleY: 1 / window.devicePixelRatio,
        });

        var MIN_WIDTH = 60;
        var tr = new Konva.Transformer({
            nodes: [shape],
            padding: 5,
            // enable only side anchors
            enabledAnchors: ['middle-left', 'middle-right'],
            // limit transformer size
            boundBoxFunc: (oldBox, newBox) => {
                if (newBox.width < MIN_WIDTH) {
                    return oldBox;
                }
                return newBox;
            },
        });
        layer.add(tr);
        layer.add(shape);

        function renderText() {
            let qlEditor = document.querySelector('.ql-editor');
            const calcWidth = shape.width() * shape.scaleX()
            qlEditor.style.width = Math.max(calcWidth, MIN_WIDTH) + 'px'
            console.log(qlEditor.style.width)
            // convert DOM into image
            html2canvas(document.querySelector('.ql-editor'), {
                backgroundColor: 'rgba(0,0,0,0)',
            }).then((canvas) => {
                if (canvas.width > 0) {
                    // show it inside Konva.Image
                    shape.image(canvas);
                }
            });
        }

        // batch updates, so we don't render text too frequently
        var timeout = null;

        function requestTextUpdate(time = 500) {
            clearTimeout(timeout)
            timeout = setTimeout(() => {
                timeout = null;
                renderText();
            }, time);
        }

        // render text on all changes
        quill.on('text-change', requestTextUpdate);
        // make initial rendering
        renderText();

        shape.on('transform', () => {
            // with enabled anchors we can only change scaleX
            // so we don't need to reset height
            // just width
            /* shap.setAttrs({
                width: Math.max(text.width() * text.scaleX(), MIN_WIDTH),
                scaleX: 1,
                scaleY: 1,
            }); */
            requestTextUpdate(200)
        });


        shape.on('dblclick dbltap', () => {
            // hide text node and transformer:
            shape.hide();
            tr.hide();

            // create textarea over canvas with absolute position
            // first we need to find position for textarea
            // how to find it?

            // at first lets find position of text node relative to the stage:
            var textPosition = shape.absolutePosition();

            // so position of textarea will be the sum of positions above:
            var areaPosition = {
                x: stage.container().offsetLeft + textPosition.x,
                y: stage.container().offsetTop + textPosition.y,
            };

            // create textarea and style it
            var textarea = document.querySelector('.ql-editor')

            // apply many styles to match text on canvas as close as possible
            // remember that text rendering on canvas and on the textarea can be different
            // and sometimes it is hard to make it 100% the same. But we will try...
            textarea.style.display = 'block';
            textarea.style.position = 'absolute';
            textarea.style.top = areaPosition.y - 40 + 'px';
            textarea.style.left = areaPosition.x - 1 + 'px';
            textarea.style.width = Math.max(shape.width() * shape.scaleX(), MIN_WIDTH) + 'px'
            /* textarea.style.height =
                shape.height() + 5 + 'px'; */
            textarea.style.border = 'none';
            // textarea.style.padding = '12px 30px 12px 15px';
            // textarea.style.margin = '0px';
            // textarea.style.overflow = 'hidden';
            textarea.style.background = 'none';
            textarea.style.outline = 'none';
            textarea.style.resize = 'none';
            textarea.style.transformOrigin = 'left top';
            textarea.style.color = shape.fill();
            textarea.style.zIndex = 999;

            rotation = shape.rotation();
            var transform = '';
            if (rotation) {
                transform += 'rotateZ(' + rotation + 'deg)';
            }

            var px = 0;
            // also we need to slightly move textarea on firefox
            // because it jumps a bit
            var isFirefox =
                navigator.userAgent.toLowerCase().indexOf('firefox') > -1;
            if (isFirefox) {
                px += 2 + Math.round(shape.fontSize() / 20);
            }
            transform += 'translateY(-' + px + 'px)';

            textarea.style.transform = transform;

            // reset height
            textarea.style.height = 'auto';
            // after browsers resized it we can set actual value
            // textarea.style.height = textarea.scrollHeight + 3 + 'px';

            textarea.focus();

            function removeTextarea() {
                textarea.style.display = 'none';
                window.removeEventListener('click', handleOutsideClick);
                shape.show();
                tr.show();
                tr.forceUpdate();
            }

            function setTextareaWidth(newWidth) {
                if (!newWidth) {
                    // set width for placeholder
                    newWidth = shape.placeholder.length * shape.fontSize();
                }
                // some extra fixes on different browsers
                var isSafari = /^((?!chrome|android).)*safari/i.test(
                    navigator.userAgent
                );
                var isFirefox =
                    navigator.userAgent.toLowerCase().indexOf('firefox') > -1;
                if (isSafari || isFirefox) {
                    newWidth = Math.ceil(newWidth);
                }

                var isEdge =
                    document.documentMode || /Edge/.test(navigator.userAgent);
                if (isEdge) {
                    newWidth += 1;
                }
                textarea.style.width = newWidth + 'px';
            }

            function handleOutsideClick(e) {
                e.stopPropagation()
                if (!textarea.contains(e.target) &&
                 !document.querySelector(".ql-toolbar").contains(e.target)) {
                    // shape.text(textarea.value);
                    removeTextarea();
                }
            }
            setTimeout(() => {
                window.addEventListener('click', handleOutsideClick);
            });
        });
        // document.querySelector('.ql-editor').style.display = 'none'
    </script>
</body>

</html>